namespace C1.Win.C1FlexGrid
{
    using C1.Win.C1FlexGrid.Util;
    using System;
    using System.Runtime.InteropServices;

    [StructLayout(LayoutKind.Sequential)]
    internal struct GridTally
    {
        private double _sum;
        private double _sum2;
        private double _cnt;
        private double _cntAll;
        private double _max;
        private double _min;
        public void Tally(object data)
        {
            if ((data != null) && (data != DBNull.Value))
            {
                this._cntAll++;
                double d = Types.CoerceDouble(data);
                if (!double.IsNaN(d))
                {
                    if (this._cnt == 0.0)
                    {
                        this._max = this._min = d;
                    }
                    this._cnt++;
                    this._sum += d;
                    this._sum2 += d * d;
                    if (d < this._min)
                    {
                        this._min = d;
                    }
                    if (d > this._max)
                    {
                        this._max = d;
                    }
                }
            }
        }

        public double Value(AggregateEnum function)
        {
            switch (function)
            {
                case AggregateEnum.Sum:
                    return this._sum;

                case AggregateEnum.Count:
                    return this._cntAll;

                case AggregateEnum.Average:
                    if (this._cnt != 0.0)
                    {
                        return (this._sum / this._cnt);
                    }
                    return 0.0;

                case AggregateEnum.Max:
                    return this._max;

                case AggregateEnum.Min:
                    return this._min;

                case AggregateEnum.Std:
                    if (this._cnt > 1.0)
                    {
                        return Math.Sqrt(this.Value(AggregateEnum.Var));
                    }
                    return 0.0;

                case AggregateEnum.Var:
                    if (this._cnt > 1.0)
                    {
                        return ((this.Value(AggregateEnum.VarPop) * this._cnt) / (this._cnt - 1.0));
                    }
                    return 0.0;

                case AggregateEnum.StdPop:
                    if (this._cnt > 1.0)
                    {
                        return Math.Sqrt(this.Value(AggregateEnum.VarPop));
                    }
                    return 0.0;

                case AggregateEnum.VarPop:
                {
                    if (this._cnt <= 1.0)
                    {
                        return 0.0;
                    }
                    double num = this._sum / this._cnt;
                    return ((this._sum2 / this._cnt) - (num * num));
                }
            }
            return 0.0;
        }
    }
}

